package com.terra.ns.imp.common.dingtalk.event

import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationListener
import java.util.concurrent.ConcurrentHashMap


/**
@author qins
@date 2023/06/05
@desc 统一定义钉钉事件处理，需处理具体事件，继承该类重写定义要处理的事件类型types后，重写对应方法
 */
abstract class AbstractDingtalkEventListener: ApplicationListener<DingtalkEvent> {

    private val log = LoggerFactory.getLogger(this::class.java)

    var types: Set<DingEventTypeEnum>? = null

    private val eventLockMap = ConcurrentHashMap<String, String>()

    final override fun onApplicationEvent(event: DingtalkEvent) {
        onEvent(event)
    }

    private fun onEvent(event: DingtalkEvent) {
        val eventType = DingEventTypeEnum.enumOf(event.eventType)
        if(types == null || types!!.contains(eventType)) {
            val eventId = event.eventId
           synchronized(getLockByEventId(eventId)) {
               try {
                   // 判断事件是否处理
                   when (eventType) {
                       DingEventTypeEnum.USER_ADD_ORG -> addUser(event)
                       DingEventTypeEnum.USER_MODIFY_ORG -> modifyUser(event)
                       DingEventTypeEnum.USER_LEAVE_ORG -> leaveUser(event)
                       DingEventTypeEnum.USER_ACTIVE_ORG -> activeUser(event)
                       DingEventTypeEnum.ORG_ADMIN_ADD -> addAdmin(event)
                       DingEventTypeEnum.ORG_ADMIN_REMOVE -> removeAdmin(event)
                       DingEventTypeEnum.ORG_DEPT_CREATE -> addDept(event)
                       DingEventTypeEnum.ORG_DEPT_MODIFY -> modifyDept(event)
                       DingEventTypeEnum.ORG_DEPT_REMOVE -> removeDept(event)
                       DingEventTypeEnum.ORG_REMOVE -> removeOrg(event)
                       DingEventTypeEnum.ORG_CHANGE -> modifyOrg(event)
                       DingEventTypeEnum.LABEL_USER_CHANGE -> changeUserLabel(event)
                       DingEventTypeEnum.LABEL_CONF_ADD -> addLabel(event)
                       DingEventTypeEnum.LABEL_CONF_DEL -> deleteLabel(event)
                       DingEventTypeEnum.LABEL_CONF_MODIFY -> modifyLabel(event)
                       DingEventTypeEnum.ATTENDANCE_CHECK_RECORD -> attendanceCheck(event)
                       DingEventTypeEnum.ATTENDANCE_SCHEDULE_CHANGE -> attendanceChangeSchedule(event)
                       DingEventTypeEnum.ATTENDANCE_OVERTIME_DURATION -> attendanceOvertime(event)
                       DingEventTypeEnum.CHECK_IN -> checkIn(event)

                       DingEventTypeEnum.BPMS_INSTANCE_CHANGE -> processInstanceChange(event)
                       DingEventTypeEnum.BPMS_TASK_CHANGE -> processTaskChange(event)
                       else -> {
                           log.warn("暂不支持的钉钉事件: {}，不处理", event.eventType)
                       }
                   }
               } finally {
                   unLockByEventId(eventId)
               }
           }
        }
    }

    open fun processInstanceChange(event: DingtalkEvent) {
        log.debug("处理钉钉审批实例开始、结束事件")
    }

    open fun processTaskChange(event: DingtalkEvent) {
        log.debug("处理钉钉审批任务开始、结束、转交事件")
    }

    open fun checkIn(event: DingtalkEvent) {
        log.debug("处理钉钉用户签到事件")
    }

    open fun attendanceOvertime(event: DingtalkEvent) {
        log.debug("处理钉钉员工加班事件")
    }

    open fun attendanceChangeSchedule(event: DingtalkEvent) {
        log.debug("处理钉钉员工排班变更事件")
    }

    open fun attendanceCheck(event: DingtalkEvent) {
        log.debug("处理钉钉员工打卡事件事件")
    }

    open fun modifyLabel(event: DingtalkEvent) {
        log.debug("处理钉钉修改角色或者角色组事件")
    }

    open fun deleteLabel(event: DingtalkEvent) {
        log.debug("处理钉钉删除角色或者角色组事件")
    }

    open fun addLabel(event: DingtalkEvent) {
        log.debug("处理钉钉增加角色或者角色组事件")
    }

    open fun changeUserLabel(event: DingtalkEvent) {
        log.debug("处理钉钉员工角色信息发生变更事件")
    }

    open fun modifyOrg(event: DingtalkEvent) {
        log.debug("处理钉钉企业信息发生变更事件")
    }

    open fun removeOrg(event: DingtalkEvent) {
        log.debug("处理钉钉企业被解散事件")
    }

    open fun removeDept(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录企业部门删除事件")
    }

    open fun modifyDept(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录企业部门修改事件")
    }

    open fun addDept(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录企业部门创建事件")
    }

    open fun removeAdmin(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录用户被取消设置管理员事件")
    }

    open fun addAdmin(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录用户被设为管理员事件")
    }

    open fun activeUser(event: DingtalkEvent) {
        log.debug("处理钉钉加入企业后用户事件")
    }

    open fun leaveUser(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录用户离职事件")
    }

    open fun modifyUser(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录用户更改事件")
    }

    open fun addUser(event: DingtalkEvent) {
        log.debug("处理钉钉通讯录用户增加事件")
    }


    private fun getLockByEventId(eventId: String): Any {
        eventLockMap.putIfAbsent(eventId, eventId)
        return eventLockMap[eventId]!!
    }

    private fun unLockByEventId(eventId: String) {
        eventLockMap.remove(eventId)
    }



}